/*
 * @Author: wuqingchun
 * @Date: 2024-06-21 16:34:37
 * @Description: 阻塞队列
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-06-22 16:25:23
 */
#ifndef __HTTP_BLOCKQUEUE_H__
#define __HTTP_BLOCKQUEUE_H__

#include <mutex>
#include <condition_variable>

template <typename T, size_t QUEUE_SIZE>
class CHTTPBlockQueue
{
private:
    static constexpr size_t QUEUE_INDEX_MASK = QUEUE_SIZE - 1;
    static_assert((QUEUE_SIZE & QUEUE_INDEX_MASK) == 0, "the size of queue must be pow of 2");

public:
    bool EnQueue(const T& refData)
    {
        std::unique_lock<std::mutex> objUL(m_mtxForArray);
        if (m_ulTail - m_ulHead >= QUEUE_SIZE)
        {
            m_objCV.notify_all();
            return false;
        }

        m_arrData[m_ulTail++ & QUEUE_INDEX_MASK] = refData;
        m_objCV.notify_all();

        return true;
    }

    bool DeQueue(T& refData)
    {
        std::unique_lock<std::mutex> objUL(m_mtxForArray);
        
        if (m_ulHead == m_ulTail)
        {
            return false;
        }

        refData = m_arrData[m_ulHead++ & QUEUE_INDEX_MASK];

        return true;
    }

    bool IsEmpty()
    {
        std::unique_lock<std::mutex> objUL(m_mtxForArray);

        return m_ulHead == m_ulTail;
    }

private:
    T        m_arrData[QUEUE_SIZE];
    size_t   m_ulHead {0};  // 队列头索引
    size_t   m_ulTail {0};  // 队列尾索引

    std::mutex m_mtxForArray;
    std::condition_variable m_objCV;
};

#endif //__HTTP_BLOCKQUEUE_H__